package com.easylive.web.controller;

import com.easylive.entity.component.EsSearchComponent;
import com.easylive.entity.component.RedisComponent;
import com.easylive.entity.constants.Constants;
import com.easylive.entity.dto.TokenUserInfoDto;
import com.easylive.entity.enums.*;
import com.easylive.entity.po.UserAction;
import com.easylive.entity.po.VideoInfo;
import com.easylive.entity.po.VideoInfoFile;
import com.easylive.entity.query.UserActionQuery;
import com.easylive.entity.query.VideoInfoFileQuery;
import com.easylive.entity.query.VideoInfoQuery;
import com.easylive.entity.request.video.WebVideoGetVideoInfoReqVO;
import com.easylive.entity.request.video.WebVideoLoadVideoReqVO;
import com.easylive.entity.request.video.WebVideoReportVideoPlayOnlineReqVO;
import com.easylive.entity.response.video.VideoInfoResultVO;
import com.easylive.entity.vo.PaginationResultVO;
import com.easylive.entity.vo.ResponseVO;
import com.easylive.exception.BusinessException;
import com.easylive.service.UserActionService;
import com.easylive.service.VideoInfoFileService;
import com.easylive.service.VideoInfoService;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: yudaxian
 * @DateTime: 2024/11/17 22:47
 **/
@RestController
@RequestMapping("/video")
public class VideoController extends ABaseController {

    @Resource
    private VideoInfoService videoInfoService;

    @Resource
    private VideoInfoFileService videoInfoFileService;

    @Resource
    private UserActionService userActionService;

    @Resource
    private RedisComponent redisComponent;

    @Resource
    private EsSearchComponent esSearchComponent;

    /**
     * 加载推荐视频
     * @return
     */
    @PostMapping("/loadRecommendVideo")
    public ResponseVO loadRecommendVideo() {

        VideoInfoQuery query = new VideoInfoQuery();
        query.setOrderBy("create_time desc");
        query.setQueryUserInfo(true);
        query.setRecommendType(VideoRecommendTypeEnum.RECOMMEND.getCode());

        List<VideoInfo> videoInfoList = videoInfoService.findListByParam(query);

        return getSuccessResponseVO(videoInfoList);
    }

    @PostMapping("/loadVideo")
    public ResponseVO loadVideo(@Validated WebVideoLoadVideoReqVO reqVO) {

        VideoInfoQuery query = new VideoInfoQuery();
        query.setPageNo(reqVO.getPageNo());
        query.setCategoryId(reqVO.getCategoryId());
        query.setpCategoryId(reqVO.getPCategoryId());
        query.setOrderBy("create_time desc");
        query.setQueryUserInfo(true);
        query.setRecommendType(VideoRecommendTypeEnum.NOT_RECOMMEND.getCode());

        PaginationResultVO<VideoInfo> page = videoInfoService.findListByPage(query);

        return getSuccessResponseVO(page);
    }

    /**
     * 获取视频详情
     * @return
     */
    @PostMapping("/getVideoInfo")
    public ResponseVO getVideoInfo(@Validated WebVideoGetVideoInfoReqVO reqVO) {

        VideoInfo dbVideoInfo = videoInfoService.getVideoInfoByVideoId(reqVO.getVideoId());
        if (ObjectUtils.isEmpty(dbVideoInfo)) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }
        VideoInfoResultVO resultVO = new VideoInfoResultVO();
        // 首先是播放量增加一次，然后需要获取这个用户有没有点赞，收藏，投币，播放量增加是返回文件流的时候增加的
        // 如果用户没登录，默认就是没点赞状态，登录了再判断有没有这个记录，这里返回一个封装的VO对象
        resultVO.setVideoInfo(dbVideoInfo);

        List<UserAction> userActionList = new ArrayList<>();
        // 获取用户行为（点赞，投币，收藏）
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        if (!ObjectUtils.isEmpty(tokenUserInfoDto)) {
            UserActionQuery actionQuery = new UserActionQuery();
            actionQuery.setUserId(tokenUserInfoDto.getUserId());
            actionQuery.setVideoId(reqVO.getVideoId());
            actionQuery.setActionTypeArray(new Integer[]{UserActionTypeEnum.VIDEO_LIKE.getType(),
                    UserActionTypeEnum.VIDEO_COLLECT.getType(), UserActionTypeEnum.VIDEO_COIN.getType()});
            userActionList = userActionService.findListByParam(actionQuery);
        }
        resultVO.setUserActionList(userActionList);
        return getSuccessResponseVO(resultVO);
    }

    /**
     * 获取文件有几个分P
     * @return
     */
    @PostMapping("/loadVideoPList")
    public ResponseVO loadVideoPList(@Validated WebVideoGetVideoInfoReqVO reqVO) {
        VideoInfo dbVideoInfo = videoInfoService.getVideoInfoByVideoId(reqVO.getVideoId());
        if (ObjectUtils.isEmpty(dbVideoInfo)) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }

        VideoInfoFileQuery query = new VideoInfoFileQuery();
        query.setVideoId(reqVO.getVideoId());
        query.setOrderBy("file_index asc");
        List<VideoInfoFile> list = videoInfoFileService.findListByParam(query);

        return getSuccessResponseVO(list);
    }

    /**
     * 播放视频，获取在线播放人数
     * 两步：第一个接口获取 m3u8 索引文件，第二个接口去请求具体的ts文件
     */
    @PostMapping("/reportVideoPlayOnline")
    public ResponseVO reportVideoPlayOnline(@Validated WebVideoReportVideoPlayOnlineReqVO reqVO) {

        /**
         * 通过 redis 的计数器给这个视频增加减少，通过轮询不断上报这个人在看，相当于心跳
         * 如果没有心跳了，通过监听 redis 失效的 key 来减数量
         */
        return getSuccessResponseVO(redisComponent.reportVideoPlayOnline(reqVO.getFileId(), reqVO.getDeviceId()));
    }

    @PostMapping("/search")
    public ResponseVO search(@Validated Integer pageNo, Integer orderType, @NotBlank String keyword) {
        // 记录热词
        redisComponent.addKeywordCount(keyword);
        // pageSize 不要从页面传，不然别人可能传个很大的
        return getSuccessResponseVO(esSearchComponent.search(true, keyword, orderType, pageNo, PageSize.SIZE20.getSize()));
    }

    @PostMapping("/getVideoRecommend")
    public ResponseVO getVideoRecommend(@Validated @NotBlank String keyword, @NotBlank String videoId) {
        List<VideoInfo> videoInfoList = esSearchComponent.search(true, keyword, SearchOrderTypeEnum.VIDEO_PLAY.getType(), null, PageSize.SIZE20.getSize()).getList();
        // 过滤掉自己
        videoInfoList = videoInfoList.stream().filter(videoInfo -> !videoInfo.getVideoId().equals(videoId)).toList();
        return getSuccessResponseVO(videoInfoList);
    }

    @PostMapping("/getSearchKeywordTop")
    public ResponseVO getSearchKeywordTop() {
        return getSuccessResponseVO(redisComponent.getKeyWordTop(Constants.LENGTH_10));
    }

    @PostMapping("/loadHotVideoList")
    public ResponseVO loadHotVideoList(@Validated Integer pageNo) {

        VideoInfoQuery videoInfoQuery = new VideoInfoQuery();
        videoInfoQuery.setPageNo(pageNo);
        videoInfoQuery.setQueryUserInfo(true);
        videoInfoQuery.setOrderBy("v.play_count desc");
        videoInfoQuery.setLastPlayHour(Constants.TIME_HOUR_24);
        PaginationResultVO<VideoInfo> page = videoInfoService.findListByPage(videoInfoQuery);

        return getSuccessResponseVO(page);
    }

}
